using System;
using NUnit.Framework;
using dnA.Math;
using dnA.Exceptions;

namespace dnA.dnAtests.Math {
	[TestFixture]
	public class ComplexDoubleTest {
		private const double TOLERENCE = 0.001;		
		[Test]
		public void EqualsTest(){
			ComplexDouble cd1 = new ComplexDouble(-1.1, 2.2);
			ComplexDouble cd2 = new ComplexDouble(-1.1, 2.2);
			ComplexDouble cd3 = new ComplexDouble(-1, 2);
			ComplexFloat cf = new ComplexFloat(-1, 2);
			Assert.IsTrue(cd1 == cd2);
			Assert.IsTrue(cd1.Equals(cd2));
			Assert.IsTrue(cd3 == cf);
			Assert.IsTrue(cd3.Equals(cf));
		}

		[Test]
		public void ConversionTest(){
			ComplexDouble cd1 = 2.2;
			ComplexFloat cf = new ComplexFloat(-1.1f, 2.2f);
			ComplexDouble cd2 = cf;
			Assert.AreEqual(cd1.Real,2.2);
			Assert.AreEqual(cd1.Imag,0);
			Assert.AreEqual(cd2.Real,-1.1,TOLERENCE);
			Assert.AreEqual(cd2.Imag,2.2,TOLERENCE);
		}		

		[Test]
			public void OperatorsTest(){
			ComplexDouble cd1 = new ComplexDouble(1.1, -2.2);
			ComplexDouble cd2 = new ComplexDouble(-3.3, 4.4);
			ComplexDouble test = cd1 * cd2;
			Assert.AreEqual(test.Real,6.05);
			Assert.AreEqual(test.Imag,12.1);
			
			test = cd1 / cd2;
			Assert.AreEqual(test.Real,-0.44);
			Assert.AreEqual(test.Imag,0.08);

			test = cd1 + cd2;
			Assert.AreEqual(test.Real,-2.2);
			Assert.AreEqual(test.Imag,2.2);
		
			test = cd1 - cd2;
			Assert.AreEqual(test.Real,4.4);
			Assert.AreEqual(test.Imag,-6.6);

			test = cd1 ^ cd2;
			Assert.AreEqual(test.Real,1.593,TOLERENCE);
			Assert.AreEqual(test.Imag,6.503,TOLERENCE);

		}
		
		[Test]
		public void NaNTest(){
			ComplexDouble cd = new ComplexDouble(Double.NaN, 1.1);
			Assert.IsTrue(cd.IsNaN());
			cd = new ComplexDouble(1.1, Double.NaN);
			Assert.IsTrue(cd.IsNaN());
			cd = new ComplexDouble(1.1,2.2);
			Assert.IsFalse(cd.IsNaN());
		}

		[Test]
		public void InfinityTest(){
			ComplexDouble cd = new ComplexDouble(Double.NegativeInfinity, 1.1);
			Assert.IsTrue(cd.IsInfinity());
			cd = new ComplexDouble(1.1, Double.NegativeInfinity);
			Assert.IsTrue(cd.IsInfinity());
			cd = new ComplexDouble(Double.PositiveInfinity, 1.1);
			Assert.IsTrue(cd.IsInfinity());
			cd = new ComplexDouble(1.1, Double.PositiveInfinity);
			Assert.IsTrue(cd.IsInfinity());
			cd = new ComplexDouble(1.1,2.2);
			Assert.IsFalse(cd.IsInfinity());
		}

		[Test]
		public void CloneTest(){
			ComplexDouble cd1 = new ComplexDouble(1.1, 2.2);
			ComplexDouble cd2 = (ComplexDouble)((ICloneable)cd1).Clone();
			Assert.AreEqual(cd1, cd2);
		}

		[Test]
		public void HashTest(){
			ComplexDouble cd = new ComplexDouble(1.1, 2.2);
			Assert.AreEqual(cd.GetHashCode(), 11);
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void NullString(){
			string s = null;
			ComplexDouble cd = new ComplexDouble(s);
		}

		[Test]
		[ExpectedException(typeof(FormatException))]
		public void FormatExceptionTest1(){
			string s = "";
			ComplexDouble cd = new ComplexDouble(s);
		}

		[Test]
		[ExpectedException(typeof(FormatException))]
		public void FormatExceptionTest2(){
			string s = "+";
			ComplexDouble cd = new ComplexDouble(s);
		}
	
		[Test]
		[ExpectedException(typeof(FormatException))]
		public void FormatExceptionTest3(){
			string s = "1i+2";
			ComplexDouble cd = new ComplexDouble(s);
		}

		[Test]
		public void ParseTest(){
			string s = "1";
			ComplexDouble cd = new ComplexDouble(s);
			Assert.AreEqual(cd.Real, 1);
			Assert.AreEqual(cd.Imag, 0);

			s = "i";
			cd = new ComplexDouble(s);
			Assert.AreEqual(cd.Real, 0);
			Assert.AreEqual(cd.Imag, 1);

			s = "2i";
			cd = new ComplexDouble(s);
			Assert.AreEqual(cd.Real, 0);
			Assert.AreEqual(cd.Imag, 2);

			s = "1 + 2i";
			cd = new ComplexDouble(s);
			Assert.AreEqual(cd.Real, 1);
			Assert.AreEqual(cd.Imag, 2);

			s = "1+2i";
			cd = new ComplexDouble(s);
			Assert.AreEqual(cd.Real, 1);
			Assert.AreEqual(cd.Imag, 2);

			s = "1 - 2i";
			cd = new ComplexDouble(s);
			Assert.AreEqual(cd.Real, 1);
			Assert.AreEqual(cd.Imag, -2);

			s = "1-2i";
			cd = new ComplexDouble(s);
			Assert.AreEqual(cd.Real, 1);
			Assert.AreEqual(cd.Imag, -2);

			s = "1+-2i";
			cd = new ComplexDouble(s);
			Assert.AreEqual(cd.Real, 1);
			Assert.AreEqual(cd.Imag, -2);
			
			s = "1 - 2i";
			cd = new ComplexDouble(s);
			Assert.AreEqual(cd.Real, 1);
			Assert.AreEqual(cd.Imag, -2);

			s = "1,2";
			cd = new ComplexDouble(s);
			Assert.AreEqual(cd.Real, 1);
			Assert.AreEqual(cd.Imag, 2);

			s = "1 , 2 ";
			cd = new ComplexDouble(s);
			Assert.AreEqual(cd.Real, 1);
			Assert.AreEqual(cd.Imag, 2);
			
			s = "1,2i";
			cd = new ComplexDouble(s);
			Assert.AreEqual(cd.Real, 1);
			Assert.AreEqual(cd.Imag, 2);

			s = "-1, -2i";
			cd = new ComplexDouble(s);
			Assert.AreEqual(cd.Real, -1);
			Assert.AreEqual(cd.Imag, -2);

			s = "(+1,2i)";
			cd = new ComplexDouble(s);
			Assert.AreEqual(cd.Real, 1);
			Assert.AreEqual(cd.Imag, 2);

			s = "(-1 , -2)";
			cd = new ComplexDouble(s);
			Assert.AreEqual(cd.Real, -1);
			Assert.AreEqual(cd.Imag, -2);

			s = "(-1 , -2i)";
			cd = new ComplexDouble(s);
			Assert.AreEqual(cd.Real, -1);
			Assert.AreEqual(cd.Imag, -2);

		
			s = "(+1e1 , -2e-2i)";
			cd = new ComplexDouble(s);
			Assert.AreEqual(cd.Real, 10);
			Assert.AreEqual(cd.Imag, -.02);		
		
			s = "(-1e1 + -2e2i)";
			cd = new ComplexDouble(s);
			Assert.AreEqual(cd.Real, -10);
			Assert.AreEqual(cd.Imag, -200);		

		}
	}
}

